package com.syh.jn.scm.domain.supplier.entity.stock;

import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.util.validator.ValidationUtils;
import com.syh.core.ddd.domain.CodeExpEnum;
import com.syh.core.ddd.domain.CodeGenerateUtil;
import com.syh.jn.scm.domain.support.SuperBusinessAggregate;
import com.syh.jn.scm.dto.supplier.stock.StockOtherOutBillMto;
import com.syh.jn.scm.dto.supplier.stock.StockOtherOutBillSto;
import com.syh.jn.scm.exception.BusinessException;
import com.syh.jn.scm.service.api.supplier.stock.enums.StockOtherOutBillEnums;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 其他出库管理
 */
@Data
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EqualsAndHashCode(callSuper = true)
public class StockOtherOutBill extends SuperBusinessAggregate<Long> {

  public StockOtherOutBill(StockOtherOutBillSto sto) {
    ExtAssert.notNull(sto, "对象为空");
    ValidationUtils.validate(sto);

    super.initDefault();
    this.status = StockOtherOutBillEnums.Status.STAY_CONFIRM.getStatus();
    this.haveRecord = StockOtherOutBillEnums.HaveRecord.NOT_RECORD.getHaveRecord();
    this.lockStatus = StockOtherOutBillEnums.LockStatus.UNLOCK.getLockStatus();
    this.code = CodeGenerateUtil.codeGenerate(CodeExpEnum.STOCK_OTHER_OUT_BILL_EXP.getCodeExp(), sto.getStorehouseId());
    ExtBeanUtils.copyProperties(sto, this);
    //明细相关
    this.items = new ArrayList<>();
    sto.getItems().stream().forEach(itemSto -> {
      this.items.add(new StockOtherOutBillItem(itemSto));
    });
    this.calculateTotalAmount();
  }

  /**
   * 计算出库总额
   */
  private void calculateTotalAmount() {
    BigDecimal totalAmount = BigDecimal.ZERO;
    for (StockOtherOutBillItem item : this.items) {
      totalAmount = totalAmount.add(item.getQuantity().multiply(item.getPrice()));
    }
    //出入库金额
    this.totalAmount = totalAmount;
  }

  /**
   * 修改其他出库单
   *
   * @param mto
   */
  public void modify(StockOtherOutBillMto mto) {
    ExtAssert.notNull(mto, "对象为空");
    ValidationUtils.validate(mto);
    ExtBeanUtils.copyProperties(mto, this);
    this.items = new ArrayList<>();
    mto.getItems().stream().forEach(itemMto -> {
      this.items.add(new StockOtherOutBillItem(itemMto));
    });
    this.lastUpdateTimeStamp = System.currentTimeMillis();
    this.calculateTotalAmount();
  }

  /**
   * 删除出入库单
   */
  public void destroy() {
    //判断当前状态是否能删除
    if (!StockOtherOutBillEnums.Status.CANCEL.getStatus().equals(this.getStatus())) {
      logger.error("destroy:其他出库单不是已取消状态,不可以删除");
      throw new RuntimeException("其他出入库单不是已取消状态,不可以删除");
    }
    if (StockOtherOutBillEnums.HaveRecord.HAVE_RECORD.getHaveRecord().equals(this.haveRecord)) {
      logger.error("destroy:其他出入库单已经生成出入库记录,不可以删除");
      throw new BusinessException("其他出入库单已经生成出入库记录,不可以删除");
    }
  }


  /**
   * 确认其他出库单
   * @param recordDateTimestamp
   */
  public void confirm(Long recordDateTimestamp) {
    this.status = StockOtherOutBillEnums.Status.CONFIRM.getStatus();
    this.haveRecord = StockOtherOutBillEnums.HaveRecord.HAVE_RECORD.getHaveRecord();
    this.lockStatus = StockOtherOutBillEnums.LockStatus.LOCK.getLockStatus();
    this.recordDateTimestamp = recordDateTimestamp == null ? System.currentTimeMillis() : recordDateTimestamp;
  }

  /**
   * 取消订单
   */
  public void cancelConfirm() {
    if (this.lockStatus.equals(StockOtherOutBillEnums.LockStatus.LOCK.getLockStatus())) {
      throw new BusinessException("其他出入库单已锁定,不可以取消");
    }
    if (!this.status.equals(StockOtherOutBillEnums.Status.CONFIRM.getStatus())) {
      throw new BusinessException("其他出入库单不是未确认状态,不可以取消");
    }
    this.status = StockOtherOutBillEnums.Status.STAY_CONFIRM.getStatus();
    this.recordDateTimestamp = null;
  }


  /**
   * 取消订单
   */
  public void cancel() {
    if (!this.status.equals(StockOtherOutBillEnums.Status.STAY_CONFIRM.getStatus())) {
      throw new BusinessException("其他出入库单不是未确认状态,不可以取消");
    }
    this.status = StockOtherOutBillEnums.Status.CANCEL.getStatus();
  }

  /**
   * 解锁
   */
  public void unLock() {
    if (!this.lockStatus.equals(StockOtherOutBillEnums.LockStatus.LOCK.getLockStatus())) {
      throw new BusinessException("只有锁定状态才能解锁");
    }
    this.lockStatus = StockOtherOutBillEnums.LockStatus.UNLOCK.getLockStatus();
  }

  /**
   * 其他出库单号
   */
  private String code;
  /**
   * 单据状态(0:未确认 1:已确认 -1:已取消)
   */
  private Short status;
  /**
   * 是否已生成出入库记录(0:未生成  1：已生成)
   */
  private Short haveRecord;
  /**
   * 出入库时间(确认)
   */
  private Long recordDateTimestamp;
  /**
   * 仓库id
   */
  private Long storehouseId;
  /**
   * 备注
   */
  private String remark;
  /**
   * 出入库总额
   */
  private BigDecimal totalAmount;
  /**
   * 录单人员id
   */
  private Long operatorId;
  /**
   * 录单日期
   */
  private Long inputDateTimestamp;
  /**
   * 锁定状态(0 未锁定 1 已锁定 )确认后自动锁定，锁定后为最终状态，将不可再修改
   */
  private Short lockStatus;
  /**
   * 报溢单项
   */
  protected List<StockOtherOutBillItem> items;
}
